﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFPractice
{

    /// <summary>
    /// 可设置编辑模式的 TextBox
    /// https://www.cnblogs.com/despacito/p/11002751.html
    /// </summary>
    public partial class LabelRenderTextBox : UserControl
    {
        public LabelRenderTextBox()
        {
            InitializeComponent();
        }

        #region events
        public event TextChangedEventHandler TextChanged;

        private void Textbox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (RequiredValue == RequiredValues.Number)
            {
                TextBox textBox = sender as TextBox;
                string text = textBox.Text;
                Regex reg = new Regex(@"^[0-9]*$");
                if (text == null || (text.Count() == 0) || !reg.IsMatch(text))
                {
                    textBox.Text = "";
                    return;
                }
            }
            this.TextChanged?.Invoke(this, e);
        }

        //清空输入框事件
        private void ExecCleanSearchText(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            if (btn == null)
                return;
            TextBox tb = btn.TemplatedParent as TextBox;
            if (tb != null)
            {
                tb.Text = "";
            }
        }

        private void Click(object sender, MouseButtonEventArgs e)
        {
            if (EditMode == EditModes.Click)
                SetEditable(true);
        }

        private void DoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (EditMode == EditModes.DoubleClick)
                SetEditable(true);
        }

        private void Lost_Focus(object sender, RoutedEventArgs e)
        {
            if (EditMode == EditModes.DoubleClick || EditMode == EditModes.Click)
                SetEditable(false);
        }
        #endregion

        #region TextProperty 
        //public string Text { get; set; }
        public string Text
        {
            get
            {
                return (string)this.GetValue(TextProperty);
            }
            set
            {
                this.SetValue(TextProperty, value);
            }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.RegisterAttached("Text", typeof(string), typeof(LabelRenderTextBox), new PropertyMetadata("", OnTextChanged));

        private static void OnTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as LabelRenderTextBox;
            if (element != null)
            {
                element.Text = e.NewValue as string;
            }
        }
        #endregion

        #region PlaceholderProperty 
        public string Placeholder
        {
            get
            {
                return (string)this.GetValue(PlaceholderProperty);
            }
            set
            {
                this.SetValue(PlaceholderProperty, value);
            }
        }

        public static readonly DependencyProperty PlaceholderProperty =
            DependencyProperty.RegisterAttached("Placeholder", typeof(string), typeof(LabelRenderTextBox), new PropertyMetadata("", OnPlaceholderChanged));

        private static void OnPlaceholderChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as LabelRenderTextBox;
            if (element != null)
            {
                element.Placeholder = e.NewValue as string;
            }
        }
        #endregion

        #region RequiredValueProperty 
        public RequiredValues RequiredValue
        {
            get { return (RequiredValues)this.GetValue(RequiredValueProperty); }
            set
            {
                this.SetValue(RequiredValueProperty, value);
            }
        }

        public static readonly DependencyProperty RequiredValueProperty =
            DependencyProperty.RegisterAttached("RequiredValue", typeof(RequiredValues), typeof(LabelRenderTextBox), new PropertyMetadata(RequiredValues.String, OnRequiredValueChanged));

        private static void OnRequiredValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as LabelRenderTextBox;
            if (element != null)
            {
                element.RequiredValue = (RequiredValues)e.NewValue;
            }
        }
        #endregion

        #region UseSearchProperty 
        public bool UseSearch
        {
            get { return (bool)this.GetValue(UseSearchProperty); }
            set
            {
                this.SetValue(UseSearchProperty, value);
                if (value)
                    this.textbox.Style = this.FindResource("mySearchTextBoxStyle") as Style;

            }
        }

        public static readonly DependencyProperty UseSearchProperty =
            DependencyProperty.RegisterAttached("UseSearch", typeof(bool), typeof(LabelRenderTextBox), new PropertyMetadata(false, OnUseSearchChanged));

        private static void OnUseSearchChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as LabelRenderTextBox;
            if (element != null)
            {
                element.UseSearch = (bool)e.NewValue;
            }
        }
        #endregion

        #region CaretIndexProperty 
        public int CaretIndex
        {
            get { return (int)this.GetValue(CaretIndexProperty); }
            set
            {
                this.SetValue(CaretIndexProperty, value);
                this.textbox.CaretIndex = value;
            }
        }

        public static readonly DependencyProperty CaretIndexProperty =
            DependencyProperty.RegisterAttached("CaretIndex", typeof(int), typeof(LabelRenderTextBox), new PropertyMetadata(0, OnCaretIndexChanged));

        private static void OnCaretIndexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as LabelRenderTextBox;
            if (element != null)
            {
                element.CaretIndex = (int)e.NewValue;
            }
        }
        #endregion

        #region SelectionStartProperty 
        public int SelectionStart
        {
            get { return (int)this.GetValue(SelectionStartProperty); }
            set
            {
                this.SetValue(SelectionStartProperty, value);
                this.textbox.SelectionStart = value;
            }
        }

        public static readonly DependencyProperty SelectionStartProperty =
            DependencyProperty.RegisterAttached("SelectionStart", typeof(int), typeof(LabelRenderTextBox), new PropertyMetadata(0, OnSelectionStartChanged));

        private static void OnSelectionStartChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as LabelRenderTextBox;
            if (element != null)
            {
                element.SelectionStart = (int)e.NewValue;
            }
        }
        #endregion

        #region EditModeProperty 
        public EditModes EditMode
        {
            get { return (EditModes)this.GetValue(EditModeProperty); }
            set
            {
                this.SetValue(EditModeProperty, value);
                if (value == EditModes.Editable)
                {
                    SetEditable(true);
                }
                else
                {
                    SetEditable(false);
                }
            }
        }

        public static readonly DependencyProperty EditModeProperty =
            DependencyProperty.RegisterAttached("EditMode", typeof(EditModes), typeof(LabelRenderTextBox), new PropertyMetadata(EditModes.Editable, OnEditModeChanged));

        private static void OnEditModeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as LabelRenderTextBox;
            if (element != null)
            {
                element.EditMode = (EditModes)e.NewValue;
            }
        }
        #endregion
        
        #region EditableProperty 

        /// <summary>
        /// 当前是否是可编辑状态;
        /// </summary>
        public bool Editable
        {
            get => (bool)this.GetValue(EditableProperty);
            set => this.SetValue(EditableProperty, value);
        }

        public static readonly DependencyProperty EditableProperty =
            DependencyProperty.RegisterAttached("Editable", typeof(bool), typeof(LabelRenderTextBox), new PropertyMetadata(false, OnEditableChanged));

        private static void OnEditableChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            if (obj is LabelRenderTextBox element)
            {
                element.Editable = (bool)e.NewValue;
            }
        }

        #endregion


        private void SetEditable(bool editable)
        {
            if (editable)
            {
                Editable = true;
                this.label.Visibility = Visibility.Collapsed;
                this.textbox.Visibility = Visibility.Visible;
            }
            else
            {
                Editable = false;
                this.label.Visibility = Visibility.Visible;
                this.textbox.Visibility = Visibility.Collapsed;
            }
        }
    }

    public enum EditModes
    {
        [Description("编辑模式")]
        Editable = 0,

        [Description("只读模式")]
        ReadOnly = 1,

        [Description("只读模式展示，单击进入编辑模式，失去焦点后恢复只读模式")]
        Click = 2,

        [Description("只读模式展示，双击进入编辑模式，失去焦点后恢复只读模式")]
        DoubleClick = 3
    }

    public enum RequiredValues
    {
        String = 0,
        Number = 1
    }
}
